package pers.cz.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pers.cz.commons.rank.Rank;
import pers.cz.commons.search.Trie;
import pers.cz.minio.MinioUtils;
import pers.cz.model.AutoCollectTestCaseSql;
import pers.cz.model.BusinessKnowLedgeTree;
import pers.cz.model.KnowLedgeBaseBusi;
import pers.cz.pub.BeanHelper;
import pers.cz.pub.CpublicFunc;
import pers.cz.pub.RespBean;
import pers.cz.pub.SequenceEnum;
import pers.cz.redis.RedisQueueProductor;
import pers.cz.service.FileUploadService;
import pers.cz.service.KnowLedgeBaseService;
import pers.cz.spring.SpringContextUtil;
import com.google.gson.Gson;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import sun.misc.BASE64Encoder;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 知识库
 * @program: PostGirl-panent
 * @description: KnowLedgeBaseController
 * @author: Cheng Zhi
 * @create: 2021-06-29 11:37
 **/
@RestController
@Api(tags = "知识库相关接口")
@RequestMapping(path = "/api/knowledgeBase")
public class KnowLedgeBaseController {

    Logger logger = LoggerFactory.getLogger(KnowLedgeBaseController.class);

    @Autowired
    MinioUtils minioUtils;

    @Autowired
    KnowLedgeBaseService knowLedgeBaseService;

    @Autowired
    RedisQueueProductor redisQueueProductor;

    @Autowired
    FileUploadService fileUploadService;

    @Autowired
    JedisPool jedisPool;

    @Autowired
    Rank rank;

    private final String BACK_NAME = "post-girl";
    private final String OBJECT_NAME = "knowLedgeBase/";

    private static AtomicBoolean initialized = new AtomicBoolean(false);

    @ApiOperation(value = "文件下载")
    @PostMapping(path = "fileDownload")
    public String fileDownload(@RequestBody Map map) {

        String fileName = (String) map.get("fileName");
        rank.add(fileName,fileName);
        String base64File = "";
        try {
            InputStream inputStream = minioUtils.getObject(BACK_NAME, OBJECT_NAME + fileName);
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024*4];
            int n = 0;
            while (-1 != (n = inputStream.read(buffer))) {
                output.write(buffer, 0, n);
            }
            byte[] bytes = output.toByteArray();

            base64File = new BASE64Encoder().encode(bytes);
            IoUtil.close(inputStream);
        } catch (Exception e) {
            logger.error("文件下载异常!", e);
        }
        return base64File;
    }
    @ApiOperation(value = "文件上传至oss")
    @PostMapping(path = "fileUpload")
    public RespBean fileUplod(@RequestParam("file") MultipartFile file, HttpServletRequest request) {

        try {

            String fileName = file.getOriginalFilename();
            InputStream inputStream = file.getInputStream();
            Integer userId = Integer.valueOf(request.getAttribute("userId").toString());
            // 将文件上传到文件服务器
            minioUtils.makeBucket("post-girl"); // 创建存储桶
            boolean isSuccess = minioUtils.putObject(BACK_NAME, OBJECT_NAME + fileName, inputStream);
            if (!isSuccess) {
                return RespBean.ok("文件上传失败");
            }
            // 将记录插入到数据库
            Long soNbr = fileUploadService.insertFileUploadBusi(fileName, userId, "知识库文件");
            // 生产一条消息到消息队列，后台启动文件处理
            redisQueueProductor.putMessage("message", String.valueOf(soNbr));

        } catch (Exception e) {
            e.printStackTrace();
            return RespBean.ok("文件上传失败");
        }
        return RespBean.ok("文件上传成功");
    }

    @ApiOperation(value = "异步上传文件至oss")
    @PostMapping(path = "fileUplodByAsync")
    public RespBean fileUplodByAsync(@RequestParam("file") MultipartFile file) {

        try {
            String fileName = file.getOriginalFilename();
            InputStream inputStream = file.getInputStream();

            // 将文件上传到文件服务器
            minioUtils.makeBucket("post-girl"); // 创建存储桶
            boolean isSuccess = minioUtils.putObject("post-girl", "knowLedgeBase/" + fileName, inputStream);
            if (!isSuccess) {
                return RespBean.ok("文件上传失败");
            }

        } catch (Exception e) {
            e.printStackTrace();
            return RespBean.ok("文件上传失败");
        }
        return RespBean.ok("文件上传成功");
    }

    @ApiOperation(value = "查询所有的文件明细")
    @PostMapping(path = "queryAllKnowLedgeBaseBusi")
    public List<KnowLedgeBaseBusi> queryAllKnowLedgeBaseBusi() {

        List<KnowLedgeBaseBusi> knowLedgeBaseBusiList  = knowLedgeBaseService.queryAllKnowLedgeBaseBusi();

        if (initialized.compareAndSet(false,true)) {
            for (KnowLedgeBaseBusi knowLedgeBaseBusi : knowLedgeBaseBusiList) {

                rank.add(knowLedgeBaseBusi.getExt1(), knowLedgeBaseBusi.getExt1());
            }

        }
        return knowLedgeBaseBusiList;
    }

    @ApiOperation(value = "根据关键字搜索文件明细")
    @PostMapping(path = "queryKnowLedgeBaseBusiByKeyWord")
    public List<KnowLedgeBaseBusi> queryKnowLedgeBaseBusiByKeyWord(@RequestBody Map map) {

        String keyWord = (String) map.get("keyWord");

        List<KnowLedgeBaseBusi> knowLedgeBaseBusiList  = knowLedgeBaseService.queryKnowLedgeBaseBusiByKeyWord(keyWord);

        return knowLedgeBaseBusiList;
    }

    @ApiOperation(value = "搜索输入联想")
    @PostMapping(path = "searchByKeyWord")
    public List<String> searchByKeyWord(@RequestBody Map map) {
        List<String> reustlts = new ArrayList<String>();
        String keyWord = (String) map.get("keyWord");
        Jedis resource = jedisPool.getResource();
        String searchTrie = resource.get("searchTrie");
        //Trie trie = JSON.parseObject(searchTrie, Trie.class);
        Trie trie = new Trie();
        Gson gson = new Gson();
        reustlts = trie.searchList(keyWord);
        resource.close();
        return reustlts;
    }

    @ApiOperation(value = "获取下载排行榜")
    @PostMapping(path = "getDownLoadRank")
    public List<KnowLedgeBaseBusi> getDownLoadRank() {

        List<KnowLedgeBaseBusi> lists = new ArrayList<>();
        rank.getRank().stream().forEach(str->{
            KnowLedgeBaseBusi knowLedgeBaseBusi = new KnowLedgeBaseBusi();
            knowLedgeBaseBusi.setExt1((String) str);
            lists.add(knowLedgeBaseBusi);
        });

        return lists;
    }

    @ApiOperation(value = "获取所有的图谱节点")
    @PostMapping(path = "quaryAllBusinessNode")
    public List<BusinessKnowLedgeTree> quaryAllBusinessNode() {

        return knowLedgeBaseService.queryAllBusinessKnowLedgeTree();
    }

    @ApiOperation(value = "添加图谱节点")
    @PostMapping(path = "addBusinessNode")
    public Integer addBusinessNode(@RequestBody Map map) {

        BusinessKnowLedgeTree tree = new BusinessKnowLedgeTree();
        Integer id = (Integer) map.get("id");
        String name = (String) map.get("name");
        String desc = (String) map.get("desc");
        if (map.get("parent_id") != null) {
            Integer parentId = (Integer) map.get("parent_id");
            tree.setParentId(parentId);
        }

        if (map.get("ext1") != null) {

            String ext1 = (String) map.get("ext1");
            tree.setExt1(ext1);
        }
        // 默认都是终节点， 如果在指定节点上添加节点那么改节点的状态将被改变
        tree.setCreatedTime(DateUtil.date());
        tree.setDescribe(desc);
        tree.setName(name);
        tree.setEndNode("1");
        tree.setId(id);
        return knowLedgeBaseService.addKonwLedgeNode(tree);
    }

    @ApiOperation(value = "修改图谱节点")
    @PostMapping(path = "updateBusinessNode")
    public Integer updateBusinessNode(@RequestBody Map map) {

        BusinessKnowLedgeTree tree = new BusinessKnowLedgeTree();
        Integer id = (Integer) map.get("id");
        tree.setId(id);
        tree.setEndNode("2");

        return knowLedgeBaseService.updateKnowLedgeNode(tree);
    }

    @ApiOperation(value = "修改图谱节点内容")
    @PostMapping(path = "updateBusinessNodeName")
    public Integer updateBusinessNodeName(@RequestBody Map map) {

        BusinessKnowLedgeTree tree = new BusinessKnowLedgeTree();
        Integer id = (Integer) map.get("id");
        String name = (String) map.get("name");
        String desc = (String) map.get("desc");
        tree.setId(id);
        tree.setName(name);
        tree.setDescribe(desc);
        return knowLedgeBaseService.updateKnowLedgeNode(tree);
    }

    @ApiOperation(value = "删除图谱节点")
    @PostMapping(path = "deleteBusinessNode")
    public Integer deleteBusinessNode(@RequestBody Map map) {
        Integer id = (Integer) map.get("id");
        return knowLedgeBaseService.deleteKonwLedgeNode(id);
    }

    @ApiOperation(value = "获取一个节点id")
    @PostMapping(path = "getId")
    public Integer getId() {
        BeanHelper beanHelper = SpringContextUtil.getBean(BeanHelper.class);
        CpublicFunc cpublicFunc  = new CpublicFunc(beanHelper);

        return Integer.valueOf(cpublicFunc.getSoNbr(SequenceEnum.BUSINESS_NODE_SEQUENCE) + "");
    }

    @ApiOperation(value = "获取所有接口")
    @PostMapping(path = "getAllBusiCode")
    public List<String> getAllBusiCode() {
        List<String> allBusiCode = knowLedgeBaseService.getAllBusiCode();
        return allBusiCode;
    }

    @ApiOperation(value = "获取所有接口sql")
    @PostMapping(path = "getAutoCollectSqlByBusiCode")
    public List<AutoCollectTestCaseSql> getAutoCollectSqlByBusiCode(@RequestBody Map map) {
        String busiCode = (String) map.get("busiCode");
        return knowLedgeBaseService.getAllSqlByBusiCode(busiCode);
    }
}
